#include "./Base.j"

// 一些公用的地图函数
library InitFunction requires SysDamage

    // 获取玩家状态，true在线，false离线了
    function isPlayerOnline takes integer pid returns boolean
        return GetPlayerController(Player(pid)) == MAP_CONTROL_USER and GetPlayerSlotState(Player(pid)) == PLAYER_SLOT_STATE_PLAYING
    endfunction

    // 获取在线玩家的数量
    function getOnlinePlayerCount takes nothing returns integer
        local integer count = 0
        local integer uid = 0
        loop
            exitwhen uid > PLAYER_NUMBER
            if isPlayerOnline(uid) then
                set count = count + 1
            endif
            set uid = uid + 1
        endloop

        return count
    endfunction

    // 计算两个坐标点之间的距离
    function getDistance takes real x1, real y1, real x2, real y2 returns real
        return SquareRoot((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2))
    endfunction
    // 获取两个单位之间的距离
    function getDistanceUnit takes unit u1, unit u2 returns real
        return getDistance(GetUnitX(u1), GetUnitY(u1), GetUnitX(u2), GetUnitY(u2))
    endfunction

    // 计算两个坐标之间的角度
    function getAngleBetweenXY takes real x1, real y1, real x2, real y2 returns real
        return bj_RADTODEG * Atan2(y2 - y1, x2 - x1)
    endfunction

    // 极坐标位移X
    function moveXYGetX takes real x, real y, real dist, real angle returns real
        return x + dist * Cos(angle * bj_DEGTORAD)
    endfunction
    // 极坐标位移Y
    function moveXYGetY takes real x, real y, real dist, real angle returns real
        return y + dist * Sin(angle * bj_DEGTORAD)
    endfunction

    // 给玩家发送信息 
    // 0表示默认系统消息
    // 1表示装备提示
    // 2表示提示
    // 3修炼秘籍的奖励
    // 10表示直接输出
    function sendMessage takes integer uid, integer status, string msg returns nothing
        if status == 0 then
            call DisplayTextToPlayer(Player(uid), 0, 0, "|cffff0000【系统】：|r" + msg)
        elseif status == 1 then
            // 装备提示，不太重要，后期可以做个开关
            call DisplayTextToPlayer(Player(uid), 0, 0, "|cff00ccff【装备】：|r" + msg)
        elseif status == 2 then
            call DisplayTextToPlayer(Player(uid), 0, 0, "|cff00ccff【提示】：|r" + msg)
        elseif status == 3 then
            // TODO 后期可以做其他美化
            call DisplayTextToPlayer(Player(uid), 0, 0, "|cff00ccff【大剑仙】：|r" + msg)
        elseif status == 10 then
            // 全部输出
            call DisplayTextToPlayer(Player(uid), 0, 0, msg)
        endif
    endfunction

    // 指定显示时间的消息
    function sendMessageTime takes integer uid, real time, string msg returns nothing
        call DisplayTimedTextToPlayer( Player(uid), 0, 0, time, "|cffff0000【系统】：|r" + msg )
    endfunction

    // 给全部玩家发送信息
    function sendMessageTimeByAllPlayer takes real time, string msg returns nothing
        local integer uid = 0
        loop
            exitwhen uid > PLAYER_NUMBER
            call sendMessageTime(uid, time, msg)
            set uid = uid + 1
        endloop
    endfunction

    // 获得矩形的随机X坐标
    function GetRectRandomX takes rect rt returns real 
        return GetRandomReal(GetRectMinX(rt), GetRectMaxX(rt))
    endfunction

    // 获得矩形的随机Y坐标
    function GetRectRandomY takes rect rt returns real
        return GetRandomReal(GetRectMinY(rt), GetRectMaxY(rt))
    endfunction

    // 使用坐标传送
    function mySetUnitPos takes integer pw_uid, unit pw_dw, real pw_x, real pw_y returns nothing

        // 移动位置
        call SetUnitPosition( pw_dw, pw_x, pw_y )
        // 选中单位
        call SelectUnitForPlayerSingle( pw_dw, Player(pw_uid) )
        // 移动镜头持续0秒
        if (GetLocalPlayer() == Player(pw_uid)) then
            // Use only local code (no net traffic) within this block to avoid desyncs.
            call PanCameraToTimed(pw_x, pw_y, 0)
        endif
        // 创建特效
        if (tx_show_status[pw_uid] == 1) then
            call YDWETimerDestroyEffect( 1.00, AddSpecialEffectTarget(player_tx_cs[pw_uid], pw_dw, "origin") )
        endif

        set pw_dw = null
    endfunction

    // 漂浮文字显示 粉色 技能显示专用
    function showPFWZ1 takes unit u, string v returns nothing
        call CreateTextTagUnitBJ( v, u, 0, 10.00, 100, 7.00, 57.00, 0 )
        call SetTextTagVisibility( bj_lastCreatedTextTag, true )
        call SetTextTagVelocityBJ( bj_lastCreatedTextTag, 64, 90 )
        call SetTextTagFadepoint( bj_lastCreatedTextTag, 1.00 )
        call YDWETimerDestroyTextTag( 1.00, bj_lastCreatedTextTag )
        set v = null
        set u = null
    endfunction

    // 显示漂浮文字，异步
    function showPFWZ1ByPlayer takes integer uid, unit u, string v returns nothing
        if (Player(uid) == GetLocalPlayer()) then
            call CreateTextTagUnitBJ( v, u, 0, 10.00, 100, 7.00, 57.00, 0 )
            call SetTextTagVisibility( bj_lastCreatedTextTag, true )
            call SetTextTagVelocityBJ( bj_lastCreatedTextTag, 64, 90 )
            call SetTextTagFadepoint( bj_lastCreatedTextTag, 1.00 )
            call YDWETimerDestroyTextTag( 1.00, bj_lastCreatedTextTag )
        endif
        set v = null
        set u = null
    endfunction

    // 新创建敌人底层函数
    // template 单位模板 unit_id：模拟的单位id  name:单位名称  pw_x：出生点x  pw_y：出生点y  pw_jd：出生点角度  
    // pw_atk：攻击力  pw_hp：生命值  pw_hj：护甲  pw_jg：攻击间隔 pw_gjjl：攻击距离  bjRate：暴击几率  bjV：暴击伤害  
    // pw_str：力量  pw_agi：敏捷  pw_int：智力  mdl：模型  mdlSuof：模型缩放
    // unit_type 0表示普通单位，1表示英雄
    // ydspeed 移动速度
    // 返回：单位
    // function myCreateUnit takes integer pid, integer template, integer unit_id, integer unit_type, string name, real pw_x, real pw_y, real pw_jd, real pw_atk, real pw_hp, real pw_hj, real pw_jg, real pw_gjjl, real bjRate, real bjV, real pw_str, real pw_agi, real pw_int, string mdl, real mdlSuof returns unit
    //     local unit u = CreateUnit( Player(pid), template, pw_x, pw_y, pw_jd )
    //     return u
    // endfunction
    function myCreateUnit takes integer pid, integer template, integer unit_id, integer unit_type, string name, real pw_x, real pw_y, real pw_jd, real pw_atk, real pw_hp, real pw_hj, real pw_jg, real pw_gjjl, real bjRate, real bjV, real pw_str, real pw_agi, real pw_int, string mdl, real mdlSuof, real ydspeed returns unit

        local real hj
        local real sm
        local real gj
        local unit u
        set u = CreateUnit( Player(pid), template, pw_x, pw_y, pw_jd )
        // 设置单位id
        call FF_SetTypeId(u, unit_id)
        // call BJDebugMsg("unit_id:"+I2S(unit_id) + " handID:" + I2S(GetHandleId(u)))
        // 单名名称
        call FF_SetUnitName(u, name)

        call FF_SetAttack(u, pw_atk)
        call FF_SetMaxHp(u, pw_hp)
        call FF_SetHp(u, pw_hp)
        call FF_SetArmor(u, pw_hj)
        // 攻击间隔
        if pw_jg > 0.0 then
            call SetUnitState( u, ConvertUnitState(0x25), pw_jg )
        endif
        // 设置攻击距离
        if pw_gjjl > 0.0 then
            call SetUnitState( u, ConvertUnitState(0x16), pw_gjjl )
        endif

        set hj = FF_GetArmor(u) * ( 1.00 + udg_diff_degree_hj[udg_game_diff])
        set sm = FF_GetMaxHp(u) * (1.00 + udg_diff_degree_sm[udg_game_diff])
        set gj = FF_GetAttack(u) * (1.00 + udg_diff_degree_gj[udg_game_diff])
        call FF_SetMaxHp(u, sm)
        call FF_SetHp(u, sm)
        call FF_SetAttack(u, gj)
        call FF_SetArmor(u, hj)
        // 增加暴击
        call FF_SetEnemyCritPro(u, bjRate)
        call FF_SetEnemyCritDamage(u, bjV)
        // 设置类型 表示是英雄
        call FF_SetUnitType(u, unit_type)

        if unit_type == 1 then
            call FF_SetStr(u, pw_str + pw_str * udg_diff_degree_pro[udg_game_diff])
            call FF_SetAgi(u, pw_agi + pw_agi * udg_diff_degree_pro[udg_game_diff])
            call FF_SetInt(u, pw_int + pw_int * udg_diff_degree_pro[udg_game_diff])
        endif

        // 设置模型
        if StringLength(mdl) > 0 then
            // call DzSetUnitModel( u, mdl )
            // 设置模型，基于内置
            call SetUnitModel( u, mdl )
            // 单位缩放
            if mdlSuof == 0.0 then
                call SetUnitScale( u, 1, 1, 1 )
            else
                call SetUnitScale( u, mdlSuof, mdlSuof, mdlSuof )
            endif
        endif

        // 移动速度
        if ydspeed > 0.0 then
            call SetUnitMoveSpeed( u, ydspeed )
        endif

        // 隐藏原生血条 基于内置
        // call SetUnitPressUIVisible (u, false)

        return u
    endfunction

    // 创建模拟属性的敌人
    // template 单位模板 unit_id：模拟的单位id name:单位名称  pw_x：出生点x  pw_y：出生点y  pw_jd：出生点角度  
    // pw_atk：攻击力  pw_hp：生命值  pw_hj：护甲  pw_jg：攻击间隔 pw_gjjl：攻击距离  bjRate：暴击几率  bjV：暴击伤害  
    // pw_str：力量  pw_agi：敏捷  pw_int：智力  mdl：模型  mdlSuof：模型缩放
    // unit_type 0表示普通单位，1表示英雄
    // ydspeed 移动速度
    // 返回：单位
    function createUByProperty takes integer template, integer unit_id, integer unit_type, string name, real pw_x, real pw_y, real pw_jd, real pw_atk, real pw_hp, real pw_hj, real pw_jg, real pw_gjjl, real bjRate, real bjV, real pw_str, real pw_agi, real pw_int, string mdl, real mdlSuof, real ydspeed returns unit
        local trigger trig = CreateTrigger()
        // return myCreateUnitNew(PLAYER_NEUTRAL_AGGRESSIVE, template, unit_id, unit_type, name, pw_x, pw_y, pw_jd, pw_atk, pw_hp, pw_hj, pw_jg, pw_gjjl, bjRate, bjV, pw_str, pw_agi, pw_int, mdl, mdlSuof)
        local unit u = myCreateUnit(PID_GAME_MONSTER, template, unit_id, unit_type, name, pw_x, pw_y, pw_jd, pw_atk, pw_hp, pw_hj, pw_jg, pw_gjjl, bjRate, bjV, pw_str, pw_agi, pw_int, mdl, mdlSuof, ydspeed)

        // 添加伤害事件
        call TriggerRegisterUnitEvent(trig, u, EVENT_UNIT_DAMAGED)
        call TriggerAddCondition(trig, Condition(function guiawuTriConditions))
        call TriggerAddAction(trig, function enemyDamagedAction)
        call FF_SetDamageEvent(u, trig)

        set trig = null
        return u
    endfunction

    // 设置单位的攻击间隔 攻击间隔-
    function setUnitAttackInterval takes unit u, real xs returns nothing
        call SetUnitState( u, ConvertUnitState(0x25), xs )
        set u = null
    endfunction

    // 增加攻击间隔
    function addUnitAttackInterval takes unit u, real xs returns nothing
        call SetUnitState( u, ConvertUnitState(0x25), ( GetUnitState(u, ConvertUnitState(0x25)) + xs ))
        set u = null
    endfunction

    // 减少单位的攻击间隔  攻击间隔-  返回的是实际减少的值
    function subUnitAttackInterval takes unit u, real interval returns real
        // 最少只能减少到0.1
        local real val = 0.1
        // 英雄攻击间隔
        local real intervalTemp = GetUnitState(u, ConvertUnitState(0x25))
        // 实际减少的值
        local real v

        // 可以减少的值 表示最大可以减少到x
        local real x = intervalTemp - val
        // 正常来说x肯定是>0的，以防万一加个判断
        if (x < 0) then
            set x = 0
        endif
        if (interval <= x) then
            set v = interval
        else
            set v = x
        endif

        // 实际执行减少
        call setUnitAttackInterval(u, intervalTemp - v)
        return v
    endfunction

endlibrary


